function gpmodel2mfile(gp,ID,filename,useAlias)
%GPMODEL2MFILE Converts a multigene regression model to a standalone M file.
%
%   GPMODEL2MFILE(GP,'best') converts the "best" model in the population to
%   a function in GPMODEL.M
%
%   GPMODEL2MFILE(GP,'best','FILENAME') converts the "best" model in the
%   population to a function in FILENAME.M
%
%   GPMODEL2MFILE(GP,'valbest','FILENAME') converts the "best" model, as
%   evaluated on the holdout validation data (if it exists), to a function
%   in FILENAME.M
%
%   GPMODEL2MFILE(GP,'testbest','FILENAME') converts the "best" model, as
%   evaluated on the test data (if it exists), to a function in FILENAME.M
%
%   GPMODEL2MFILE(GP,ID,'FILENAME') converts the model with numeric
%   identifier ID in the population to a function in FILENAME.M
%
%   GPMODEL2MFILE(GP,ID,'FILENAME',USEALIAS) does the same but uses
%   variable aliases (if defined in gp.nodes.inputs.names) if USEALIAS is
%   TRUE.
%
%   GPMODEL2MFILE(GP,GPMODEL) operates on the GPMODEL struct representing a
%   multigene regression model, i.e. the struct returned by the functions
%   GPMODEL2STRUCT or GENES2GPMODEL.
%
%   Remarks: 
%
%   This function is designed for use with multigene symbolic regression
%   models created with the REGRESSMULTI_FITFUN fitness function (or
%   variant thereof having a file name beginning 'REGRESSMULTI').
%
%   Note:
%
%   Requires Symbolic Math Toolbox.
%
%   Copyright (c) 2009-2015 Dominic Searson 
%
%   GPTIPS 2
%
%   See also GPMODELGENES2MFILE, GPMODEL2SYM, GPMODELREPORT,
%   GPMODEL2STRUCT, GPMODEL2FUNC

if nargin < 2
    disp('Usage is GPMODEL2MFILE(GP,ID) where ID is the numeric identifier of the desired model');
    disp('or GPMODEL2MFILE(GP,''BEST'') to convert the best model of run');
    disp('or GPMODEL2MFILE(GP,''VALBEST'') to convert the best validation model of run.');
    disp('or GPMODEL2MFILE(GP,''TESTBEST'') to convert the best test model of run.');
    return;
end

if ~strncmpi('regressmulti',func2str(gp.fitness.fitfun),12)
    error('GPMODEL2MFILE may only be used for multigene symbolic regression problems.');
end

if nargin < 3 || isempty(filename)
    filename = 'gpmodel';
end

if nargin < 4 || isempty(useAlias)
    useAlias = false;
end

if ~ischar(filename)
    error('The filename parameter must be a string.');
end

if gp.info.toolbox.symbolic

    %simplify and get sym object for overall model
    exprSym = gpmodel2sym(gp,ID,false,useAlias);

    if isempty(exprSym)
        error('Not a valid model ID or model selector');
    end
    
    %vectorise the whole multigene model and extract to string
    vectorisedModelStr = ['ypred=' vectorize(exprSym)];

    %replace x1,x2,x3 etc with x(:,1), x(:,2), x(:,3) etc.
    pat='x(\d+)';
    vectorisedModelStr = regexprep(vectorisedModelStr,pat,'x(:,$1)');

    if strcmp(filename(end-1:end),'.m')
        filename = filename(1:end-2);
    end

    %open file and write m file header etc
    fid = fopen([filename '.m'],'w+');

    fprintf(fid,['function ypred=' filename '(x)']);
    fprintf(fid,'\n');
    fprintf(fid,['%%'   upper(filename) ...
        ' This model file was automatically generated by the GPTIPS 2 function gpmodel2mfile on ' datestr(now)]);
    fprintf(fid,'\n\n');

    %write model
    fprintf(fid,[vectorisedModelStr ';']);
    fprintf(fid,'\n');
    fclose(fid);
    disp(['Model sucessfully written to ' filename '.m']);
else
    error('The Symbolic Math Toolbox is required to use this function.');
end
